home *** CD-ROM | disk | FTP | other *** search
- /*
- * File: DZDZSliderCDEF.c
- * Author: Dan Venolia
- *
- * Copyright © 1996 Apple Computer, Inc.
- */
-
- #include <Controls.h>
- #include <Events.h>
- #include <Fonts.h>
- #include <Memory.h>
- #include <QDOffscreen.h>
- #include <Quickdraw.h>
-
-
- enum {
- kThumbLeft = 13, // Amount of thumb hanging to the left
- kThumbRight = kThumbLeft+1 // One more because of drop shadow
- };
-
-
- typedef struct PrivateData {
- GWorldPtr offscreen;
- short offset;
- short origValue;
- } PrivateData;
-
-
- typedef struct DragRecord {
- Rect limitRect;
- Rect slopRect;
- short axis;
- } DragRecord;
-
-
- pascal long main(
- short inVariation,
- ControlHandle inControl,
- short inMessage,
- long inData);
-
- static void DoInitCntl(
- ControlHandle inControl,
- short inVariation);
-
- static void DoDispCntl(
- ControlHandle inControl);
-
- static void DoDrawCntl(
- ControlHandle inControl,
- short inVariation,
- long inPartCode);
-
- static long DoTestCntl(
- ControlHandle inControl,
- short inVariation,
- Point inPoint);
-
- static void DoPosCntl(
- ControlHandle inControl,
- short inVariation,
- Point inDelta);
-
- static void DoThumbCntl(
- ControlHandle inControl,
- short inVariation,
- DragRecord* inDragRecord);
-
- static void DoDragCntl(
- ControlHandle inControl,
- short inVariation);
-
- static void DoCalcCntlRgn(
- ControlHandle inControl,
- short inVariation,
- RgnHandle ioRegion);
-
- static void DoCalcThumbRgn(
- ControlHandle inControl,
- short inVariation,
- RgnHandle ioRegion);
-
- static short ValToPos(
- ControlHandle inControl,
- short inVariation);
-
- static void PosToVal(
- ControlHandle inControl,
- short inVariation,
- short inPosition);
-
- static void NumToPStr(
- Str255 outStr,
- long inValue);
-
-
- /* =============================================================================
- * main (external)
- *
- * The main entry point. Dispatches on inMessage.
- * ========================================================================== */
- pascal long main(
- short inVariation,
- ControlHandle inControl,
- short inMessage,
- long inData)
- {
- long result;
- GrafPtr oldPort;
-
- result = 0;
-
- GetPort(&oldPort);
- SetPort((*inControl)->contrlOwner);
-
- if ((*inControl)->contrlData != NULL || inMessage == initCntl)
- {
- switch (inMessage)
- {
- case drawCntl:
- DoDrawCntl(inControl, inVariation, inData);
- break;
-
- case testCntl:
- result = DoTestCntl(inControl, inVariation, * (Point*) &inData);
- break;
-
- case calcCRgns: // Only on 24-bit systems
- if (inData < 0)
- {
- DoCalcThumbRgn(inControl, inVariation, (RgnHandle) (inData & 0x0FFFFFFF));
- }
- else
- {
- DoCalcCntlRgn(inControl, inVariation, (RgnHandle) inData);
- }
- break;
-
- case initCntl:
- DoInitCntl(inControl, inVariation);
- break;
-
- case dispCntl:
- DoDispCntl(inControl);
- break;
-
- case posCntl:
- DoPosCntl(inControl, inVariation, * (Point*) &inData);
- break;
-
- case thumbCntl:
- DoThumbCntl(inControl, inVariation, (DragRecord*) inData);
- break;
-
- case dragCntl:
- DoDragCntl(inControl, inVariation);
- result = 1;
- break;
-
- case autoTrack:
- // not needed
- break;
-
- case calcCntlRgn:
- DoCalcCntlRgn(inControl, inVariation, (RgnHandle) inData);
- break;
-
- case calcThumbRgn:
- DoCalcThumbRgn(inControl, inVariation, (RgnHandle) inData);
- break;
-
- case drawThumbOutline:
- // ???
- break;
- }
- }
-
- SetPort(oldPort);
-
- return result;
- }
-
-
- /* =============================================================================
- * DoInitCntl (internal)
- *
- * Initializes the control. Allocates our private data.
- * ========================================================================== */
- void DoInitCntl(
- ControlHandle inControl,
- short inVariation)
- {
- PrivateData** privateData;
-
- // Allocate our private data
- (*inControl)->contrlData = NewHandle(sizeof(PrivateData));
- if ((*inControl)->contrlData == NULL || MemError() != noErr)
- {
- DoDispCntl(inControl);
- return;
- }
-
- // Initialize fields
- privateData = (PrivateData**) (*inControl)->contrlData;
- (*privateData)->offscreen = NULL;
- (*privateData)->offset = 0;
- (*privateData)->origValue = 0;
-
- // Allocate the offscreen gworld
- if (NewGWorld(
- &(*privateData)->offscreen,
- 32,
- &(*inControl)->contrlRect,
- NULL,
- NULL,
- 0) != noErr)
- {
- DoDispCntl(inControl);
- return;
- }
- }
-
-
- /* =============================================================================
- * DoDispCntl (internal)
- *
- * Disposes of the private data.
- * ========================================================================== */
- void DoDispCntl(
- ControlHandle inControl)
- {
- PrivateData** privateData = (PrivateData**) (*inControl)->contrlData;
-
- if (privateData != NULL)
- {
- if ((*privateData)->offscreen != NULL)
- {
- DisposeGWorld((*privateData)->offscreen);
- (*privateData)->offscreen = NULL;
- }
-
- DisposeHandle((Handle) privateData);
- (*inControl)->contrlData = NULL;
- }
- }
-
-
- /* =============================================================================
- * DoDrawCntl (internal)
- *
- * Displays the slider. It renders it offscreen, then copies it on. The
- * inPartCode is ignored.
- * ========================================================================== */
- void DoDrawCntl(
- ControlHandle inControl,
- short inVariation,
- long inPartCode)
- {
- PrivateData** privateData = (PrivateData**) (*inControl)->contrlData;
- GWorldPtr offscreen = (*privateData)->offscreen;
- CGrafPtr oldGrafPort;
- GDHandle oldGDevice;
- Point center;
- Rect bounds;
- Rect thumb;
- RGBColor color;
- RGBColor backColor;
- RGBColor foreColor;
- Str255 value;
- Boolean colorWindow;
-
- if ((*inControl)->contrlVis)
- {
- // Handle changing control size
- if (offscreen->portRect.right - offscreen->portRect.left <
- (*inControl)->contrlRect.right - (*inControl)->contrlRect.left ||
- offscreen->portRect.bottom - offscreen->portRect.top <
- (*inControl)->contrlRect.bottom - (*inControl)->contrlRect.top)
- {
- if (UpdateGWorld(
- &(*privateData)->offscreen,
- 32,
- &(*inControl)->contrlRect,
- NULL,
- NULL,
- 0) != noErr)
- {
- DoDispCntl(inControl);
- return;
- }
- }
-
- // Prepare for drawing
- LockPixels(offscreen->portPixMap);
-
- GetGWorld(&oldGrafPort, &oldGDevice);
- SetGWorld(offscreen, NULL);
-
- colorWindow = ((*inControl)->contrlOwner->portBits.rowBytes & 0xC000) != 0;
-
- // Find the thumb center
- bounds = offscreen->portRect;
- center.v = (bounds.top+bounds.bottom+1) >> 1;
- center.h = ValToPos(inControl, inVariation);
-
- // Clear to the same background as the owner window
- if (colorWindow)
- {
- color.red = color.green = color.blue = 0x0000;
- RGBForeColor(&((CGrafPtr) (*inControl)->contrlOwner)->rgbBkColor);
- PaintRect(&offscreen->portRect);
- }
- else
- {
- EraseRect(&offscreen->portRect);
- }
-
- // Draw the slider
- bounds.top = center.v - 4;
- bounds.bottom = center.v + 4;
-
- if ((*inControl)->contrlHilite != 255)
- {
- color.red = color.green = color.blue = 0xAAAA;
- RGBForeColor(&color);
- PaintRoundRect(&bounds, 8, 8); // Draw the background
-
- color.red = color.green = color.blue = 0x2222;
- }
- else
- {
- color.red = color.green = color.blue = 0x8888;
- }
-
- RGBForeColor(&color);
- FrameRoundRect(&bounds, 8, 8); // Draw the outer roundrect
-
- InsetRect(&bounds, 2, 2);
- FrameRoundRect(&bounds, 4, 4); // Draw the inner roundrect
-
- // Draw the thumb
- if ((*inControl)->contrlHilite != 255)
- {
- // Draw the thumb graphic
- thumb.top = offscreen->portRect.top;
- thumb.left = center.h-kThumbLeft;
- thumb.bottom = offscreen->portRect.bottom;
- thumb.right = center.h+kThumbRight;
-
- color.red = color.green = color.blue = 0xAAAA;
- RGBForeColor(&color);
-
- bounds = thumb;
- thumb.bottom -= 1;
- bounds.left += 2;
- bounds.top = thumb.bottom;
- PaintRect(&bounds); // Draw the drop shadow horiz part
-
- bounds = thumb;
- thumb.right -= 1;
- bounds.top += 1;
- bounds.left = thumb.right;
- PaintRect(&bounds); // Draw the drop shadow vert part
-
- color.red = color.green = color.blue = 0x2222;
- RGBForeColor(&color);
- FrameRect(&thumb); // Draw the thumb outline
-
- InsetRect(&thumb, 1, 1);
-
- color.red = color.green = color.blue = 0xCCCC;
- RGBForeColor(&color);
- PaintRect(&thumb); // Draw the thumb background
-
- color.red = color.green = color.blue = 0x8888;
- RGBForeColor(&color);
-
- bounds.top = thumb.bottom-1;
- bounds.left = thumb.left+1;
- bounds.bottom = thumb.bottom;
- bounds.right = thumb.right;
- PaintRect(&bounds); // Draw the dark shadow horiz part
-
- bounds.top = thumb.top+1;
- bounds.left = thumb.right-1;
- bounds.bottom = thumb.bottom-1;
- bounds.right = thumb.right;
- PaintRect(&bounds); // Draw the dark shadow vert part
-
- color.red = color.green = color.blue = 0xAAAA;
- RGBForeColor(&color);
-
- bounds.top = thumb.bottom-2;
- bounds.left = thumb.left+2;
- bounds.bottom = thumb.bottom-1;
- bounds.right = thumb.right-1;
- PaintRect(&bounds); // Draw the light shadow horiz part
-
- bounds.top = thumb.top+2;
- bounds.left = thumb.right-2;
- bounds.bottom = thumb.bottom-2;
- bounds.right = thumb.right-1;
- PaintRect(&bounds); // Draw the light shadow vert part
-
- color.red = color.green = color.blue = 0xEEEE;
- RGBForeColor(&color);
-
- bounds.top = thumb.top;
- bounds.left = thumb.left;
- bounds.bottom = thumb.top+2;
- bounds.right = thumb.left+2;
- PaintRect(&bounds); // Draw the hilite topleft part
-
- bounds.top = thumb.top+1;
- bounds.left = thumb.left+2;
- bounds.bottom = thumb.top+2;
- bounds.right = thumb.right-1;
- PaintRect(&bounds); // Draw the hilite horiz part
-
- bounds.top = thumb.top+2;
- bounds.left = thumb.left+1;
- bounds.bottom = thumb.bottom-2;
- bounds.right = thumb.left+2;
- PaintRect(&bounds); // Draw the hilite vert part
-
- // Draw the text in the thumb
- color.red = color.green = color.blue = 0x0000;
- RGBForeColor(&color);
-
- TextFont(geneva);
- TextSize(9);
-
- NumToPStr(value, (*inControl)->contrlValue);
-
- MoveTo(center.h - ((StringWidth(value)+1) >> 1), center.v + 3);
- DrawString(value);
- }
-
- // Copy it on screen
- SetGWorld(oldGrafPort, oldGDevice);
-
- if (colorWindow)
- {
- backColor = ((CGrafPtr) (*inControl)->contrlOwner)->rgbBkColor;
- foreColor = ((CGrafPtr) (*inControl)->contrlOwner)->rgbFgColor;
-
- color.red = color.green = color.blue = 0xFFFF;
- RGBBackColor(&color);
-
- color.red = color.green = color.blue = 0x0000;
- RGBForeColor(&color);
- }
-
- CopyBits(
- (BitMap*) *offscreen->portPixMap,
- &(*inControl)->contrlOwner->portBits,
- &offscreen->portRect,
- &(*inControl)->contrlRect,
- srcCopy,
- nil);
-
- if (colorWindow)
- {
- RGBBackColor(&backColor);
- RGBForeColor(&foreColor);
- }
-
- // Clean up
- UnlockPixels(offscreen->portPixMap);
- }
- }
-
-
- /* =============================================================================
- * DoTestCntl (internal)
- *
- * Returns the part code of the hit control, or zero if none.
- * ========================================================================== */
- long DoTestCntl(
- ControlHandle inControl,
- short inVariation,
- Point inPoint)
- {
- PrivateData** privateData = (PrivateData**) (*inControl)->contrlData;
- long partCode;
- short position;
- Rect thumb;
-
- partCode = 0;
-
- if ((*inControl)->contrlVis && (*inControl)->contrlHilite != 255)
- {
- if (PtInRect(inPoint, &(*inControl)->contrlRect))
- {
- // Compute the thumb rect
- position = ValToPos(inControl, inVariation);
-
- thumb = (*inControl)->contrlRect;
- thumb.left = position-kThumbLeft;
- thumb.right = position+kThumbRight;
-
- // Check whether we're inside it
- if (PtInRect(inPoint, &thumb))
- {
- (*privateData)->offset = position-inPoint.h;
- }
- else
- {
- (*privateData)->offset = 0;
- }
-
- (*privateData)->origValue = (*inControl)->contrlValue;
-
- partCode = kControlIndicatorPart;
- }
- }
-
- return partCode;
- }
-
-
- /* =============================================================================
- * DoPosCntl (internal)
- *
- * Called at mouse-up time with the movement delta.
- * ========================================================================== */
- void DoPosCntl(
- ControlHandle inControl,
- short inVariation,
- Point inDelta)
- {
- // Do nothing -- we've already done the deed
- }
-
-
- /* =============================================================================
- * DoThumbCntl (internal)
- *
- * Fills out the slop, limit and axis fields of the drag record.
- * ========================================================================== */
- void DoThumbCntl(
- ControlHandle inControl,
- short inVariation,
- DragRecord* inDragRecord)
- {
- // Do nothing since we handle the drag ourselves
- }
-
-
- /* =============================================================================
- * DoDragCntl (internal)
- *
- * Called repeatedly during drag to track mouse movement.
- * ========================================================================== */
- void DoDragCntl(
- ControlHandle inControl,
- short inVariation)
- {
- PrivateData** privateData = (PrivateData**) (*inControl)->contrlData;
- Point mousePt;
- short value;
- Rect slop;
-
- slop = (*inControl)->contrlRect;
- InsetRect(&slop, -100, -50);
-
- do
- {
- value = (*inControl)->contrlValue;
-
- GetMouse(&mousePt);
- if (PtInRect(mousePt, &slop))
- {
- // Still inside -- track the pointer
- PosToVal(inControl, inVariation, mousePt.h + (*privateData)->offset);
- }
- else
- {
- // Outside -- restore original value
- (*inControl)->contrlValue = (*privateData)->origValue;
- }
-
- // Draw if changed
- if (value != (*inControl)->contrlValue)
- {
- DoDrawCntl(inControl, inVariation, 0);
- }
- }
- while (StillDown());
- }
-
-
- /* =============================================================================
- * DoCalcCntlRgn (internal)
- *
- * Fills in ioRegion with the control region.
- * ========================================================================== */
- void DoCalcCntlRgn(
- ControlHandle inControl,
- short inVariation,
- RgnHandle ioRegion)
- {
- RectRgn(ioRegion, &(*inControl)->contrlRect);
- }
-
-
- /* =============================================================================
- * DoCalcThumbRgn (internal)
- *
- * Fills in ioRegion with the thumb region.
- * ========================================================================== */
- void DoCalcThumbRgn(
- ControlHandle inControl,
- short inVariation,
- RgnHandle ioRegion)
- {
- short position;
- Rect thumb;
-
- position = ValToPos(inControl, inVariation);
-
- thumb = (*inControl)->contrlRect;
- thumb.left = position-kThumbLeft;
- thumb.right = position+kThumbRight;
-
- RectRgn(ioRegion, &thumb);
- }
-
-
- /* =============================================================================
- * ValToPos (internal)
- *
- * Converts the current control value into a position.
- * ========================================================================== */
- static short ValToPos(
- ControlHandle inControl,
- short inVariation)
- {
- short denom;
- short position;
-
- denom = (*inControl)->contrlMax - (*inControl)->contrlMin;
-
- position = ((long)((*inControl)->contrlValue - (*inControl)->contrlMin) *
- (((*inControl)->contrlRect.right - kThumbRight) -
- ((*inControl)->contrlRect.left + kThumbLeft)) + ((denom+1)>>1)) / denom +
- ((*inControl)->contrlRect.left + kThumbLeft);
-
- if (position < (*inControl)->contrlRect.left + kThumbLeft)
- {
- position = (*inControl)->contrlRect.left + kThumbLeft;
- }
-
- if (position > (*inControl)->contrlRect.right - kThumbRight)
- {
- position = (*inControl)->contrlRect.right - kThumbRight;
- }
-
- return position;
- }
-
-
- /* =============================================================================
- * PosToVal (internal)
- *
- * Changes the control value to reflect the given position.
- * ========================================================================== */
- static void PosToVal(
- ControlHandle inControl,
- short inVariation,
- short inPosition)
- {
- short denom;
-
- denom = ((*inControl)->contrlRect.right - kThumbRight)-
- ((*inControl)->contrlRect.left + kThumbLeft);
-
- (*inControl)->contrlValue = ((long)(inPosition - ((*inControl)->contrlRect.left + kThumbLeft)) *
- ((*inControl)->contrlMax-(*inControl)->contrlMin) + ((denom+1)>>1)) / denom +
- (*inControl)->contrlMin;
-
- if ((*inControl)->contrlValue < (*inControl)->contrlMin)
- {
- (*inControl)->contrlValue = (*inControl)->contrlMin;
- }
-
- if ((*inControl)->contrlValue > (*inControl)->contrlMax)
- {
- (*inControl)->contrlValue = (*inControl)->contrlMax;
- }
- }
-
-
- /* =============================================================================
- * NumToPStr (internal)
- *
- * Converts the number to a string. Using the toolbox incurred too much junk
- * in the link for me to feel good.
- * ========================================================================== */
- void NumToPStr(
- Str255 outStr,
- long inValue)
- {
- unsigned char* p;
- long val;
- long place;
- long digit;
- Boolean leading;
-
- p = &outStr[1];
-
- if (inValue == 0)
- {
- *p++ = 0;
- }
- else
- {
- // Strip the negative
- val = inValue;
- if (val < 0)
- {
- *p++ = '-';
- val = -val;
- }
-
- // Convert from MSD on down
- place = 1000000000;
- leading = true;
- do
- {
- // Extract the digit
- digit = val/place;
- val -= digit*place;
-
- // Use it
- if (digit != 0 || !leading)
- {
- *p++ = '0'+digit;
- leading = false;
- }
-
- // Prepare for the next digit
- place /= 10;
- }
- while (place != 0);
- }
-
- outStr[0] = p-outStr-1;
- }
-
-
-